import numpy as np
import struct
import time
import threading
import serial
import serial.tools.list_ports
from enum import Enum
import datetime

class cmd_type(Enum):
    CMD_HEARTBEAT = 0x1  #心跳包
    CMD_QUERY_T = 0x2   #查询温度
    CMD_GETLOG = 0x3 #日志
    CMD_SELF_CHECK = 0x4 #自检
    CMD_Reset = 0x5  #恢复出厂设置
    CMD_CHANGE_IP = 0x6 #修改ip
    CMD_QUERY_IP = 0x7  #查询ip
    CMD_SOURCE_SELECT_FUN = 0x8   #初始化
    CMD_WRITE_GAIN_REGISTER = 0x09   #写入增益值
    CMD_WRITE_AD9910_REGISTER = 0x0A  #写入AD9910寄存器
    CMD_READ_AD9910_REGISTER = 0x0B  #读取AD9910寄存器
    CMD_CHSTATUS = 0x0C  #通道状态
    CMD_PROFILEPIN = 0x0D #profilepin
    CMD_PROMODE = 0x0E  #pro模式
    CMD_DEVONOFF = 0xF  #判断设备是否开启
    CMD_TRIGGER = 0x10  #触发信号
    CMD_MATRIX = 0x11  #矩阵数据
    CMD_WRITE_AD9910_REGISTERSYNC = 0x12  # 单步写入寄存器
    CMD_WRITE_UPDATA_IORESET = 0x13  # 单步写入寄存器
    CMD_MLENGTH = 0x14  # 单步写入寄存器
    CMD_PINDEFULAT = 0x15
    CMD_FANC = 0x16
    CMD_TRIGGERDELAY = 0x17

class cmd_base():
    head_B = 0xf4f5f6f7
    cmd = 0
    lenth = 512
    da_cmd = []
    zero =[]
    def __init__(self):
        pass
    def build(self):
        format_str = '3I' + str(len(self.da_cmd)) + 's'
        self.zero.clear()
        for i in range(512-len(self.da_cmd)):
            self.zero.append(0)
        send_str = struct.pack(format_str, self.head_B, self.cmd, self.lenth, np.asarray(self.da_cmd, np.uint8).tobytes())
        # send_str = np.asarray(self.head_B, np.uint32).tobytes()
        # send_str += np.asarray(self.cmd, np.uint32).tobytes()
        # send_str += np.asarray(self.lenth, np.uint32).tobytes()
        # send_str += np.asarray(self.ad_da_cmd, np.uint8).tobytes()
        send_str += np.asarray(self.zero, np.uint8).tobytes()
        # print(len(send_str))
        return send_str
class matcmd_base():
    head_B = 0xf7f6f5f4
    cmd = 0
    lenth = 512
    da_cmd = []
    zero =[]
    def __init__(self):
        pass
    def build(self):
        format_str = '3I' + str(len(self.da_cmd)) + 's'
        self.zero.clear()
        for i in range(512-len(self.da_cmd)):
            self.zero.append(0)
        send_str = struct.pack(format_str, self.head_B, self.cmd, self.lenth, np.asarray(self.da_cmd, np.uint8).tobytes())
        # send_str = np.asarray(self.head_B, np.uint32).tobytes()
        # send_str += np.asarray(self.cmd, np.uint32).tobytes()
        # send_str += np.asarray(self.lenth, np.uint32).tobytes()
        # send_str += np.asarray(self.ad_da_cmd, np.uint8).tobytes()
        send_str += np.asarray(self.zero, np.uint8).tobytes()
        # print(len(send_str))
        return send_str

class delay_1ms():
    def __init__(self):
        pass
    def fun(self):
        delay_mark = time.time()
        while True:
            offset = time.time() - delay_mark
            if offset > 0.0011:
                break

class heartpack(cmd_base):
    head = 0x55
    id = 0x1
    len = 0
    tpye = cmd_type.CMD_HEARTBEAT.value
    herat = [ord('Z'), ord('W'), ord('D'), ord('X')]
    def __init__(self):
        super().__init__()
        pass
    def creatpack(self):
        self.da_cmd = [self.head, self.id, self.len, self.tpye]
        self.da_cmd += self.herat
        return self.build()

class changeip(cmd_base):
    head = 0x55
    id = 0x1
    len = 0
    tpye = cmd_type.CMD_CHANGE_IP.value
    def __init__(self, IP):
        super().__init__()
        self.ip = IP
    def creatpack(self):
        ip = self.ip.split('.')
        if len(ip) != 4:
            print('请检查ip格式')
            return
        if (int(ip[0]) < 0) | (int(ip[0]) > 255) | (int(ip[1]) < 0) | (int(ip[1]) > 255) | (int(ip[2]) < 0) | (
                int(ip[2]) > 255) | (int(ip[3]) < 0) | (int(ip[3]) > 255):
            print('请输入正确的ip')
            return
        self.da_cmd = [self.head, self.id, self.len, self.tpye, ip[0], ip[1], ip[2], ip[3]]
        return self.build()

class fanctrl(cmd_base):
    head = 0x55
    id = 0x1
    len = 0
    tpye = cmd_type.CMD_FANC.value
    def __init__(self, SPEED):
        super().__init__()
        self.speed = SPEED
    def creatpack(self):
        self.da_cmd = [self.head, self.id, self.len, self.tpye, (self.speed)&0xff, (self.speed>>8)&0xff, (self.speed>>16)&0xff, (self.speed>>24)&0xff]
        return self.build()

class settirgdelay(cmd_base):
    head = 0x55
    id = 0x1
    len = 0
    tpye = cmd_type.CMD_TRIGGERDELAY.value
    def __init__(self, N):
        super().__init__()
        self.n = N
    def creatpack(self):
        self.da_cmd = [self.head, self.id, self.len, self.tpye, (self.n)&0xff, (self.n>>8)&0xff, (self.n>>16)&0xff, (self.n>>24)&0xff]
        return self.build()

class selfcheckpack(cmd_base):
    head = 0x55
    id = 0x1
    len = 0
    tpye = cmd_type.CMD_SELF_CHECK.value
    def __init__(self):
        super().__init__()
        pass
    def creatpack(self):
        self.da_cmd = [self.head, self.id, self.len, self.tpye]
        return self.build()

class Sou_sel_fun(cmd_base):
    head = 0x55
    id = 0x1
    len = 0
    tpye = cmd_type.CMD_SOURCE_SELECT_FUN.value
    def __init__(self, R, F, H, S):
        super().__init__()
        self.REFERNCECLOCK = R
        self.FRESELECT = F
        self.HMC7044 = H
        self.SYNCIN = S
    def creatpack(self):
        self.da_cmd = [self.head, self.id, self.len, self.tpye, self.REFERNCECLOCK, self.FRESELECT, self.HMC7044, self.SYNCIN]
        return self.build()

class HMC542_write(cmd_base):
    head = 0x55
    id = 0x1
    len = 0
    tpye = cmd_type.CMD_WRITE_GAIN_REGISTER.value
    def __init__(self, CH, VALUE):
        super().__init__()
        self.ch = CH
        self.value = int(VALUE*2)
    def creatpack(self):
        self.da_cmd = [self.head, self.id, self.len, self.tpye, self.ch,  (self.value)&0xff, (self.value>>8)&0xff, (self.value>>16)&0xff, (self.value>>24)&0xff]
        return self.build()

class ad9910_reg_write(cmd_base):
    head = 0x55
    id = 0x1
    len = 0
    tpye = cmd_type.CMD_WRITE_AD9910_REGISTER.value
    def __init__(self, CH, ADDR, HVALUE, LVALUE):
        super().__init__()
        self.ch = CH
        self.addr = ADDR
        self.hvalue = HVALUE
        self.lvalue = LVALUE
    def creatpack(self):
        self.da_cmd = [self.head, self.id, self.len, self.tpye, self.ch, self.addr,(self.hvalue>>0)&0xff, (self.hvalue>>8)&0xff, (self.hvalue>>16)&0xff, (self.hvalue>>24)&0xff,
                       (self.lvalue>>0)&0xff, (self.lvalue>>8)&0xff, (self.lvalue>>16)&0xff, (self.lvalue>>24)&0xff]
        return self.build()

class ad9910_reg_writesync(cmd_base):
    head = 0x55
    id = 0x1
    len = 0
    tpye = cmd_type.CMD_WRITE_AD9910_REGISTERSYNC.value
    def __init__(self, CH, ADDR, HVALUE, LVALUE):
        super().__init__()
        self.ch = CH
        self.addr = ADDR
        self.hvalue = HVALUE
        self.lvalue = LVALUE
    def creatpack(self):
        self.da_cmd = [self.head, self.id, self.len, self.tpye, self.ch, self.addr,(self.hvalue>>0)&0xff, (self.hvalue>>8)&0xff, (self.hvalue>>16)&0xff, (self.hvalue>>24)&0xff,
                       (self.lvalue>>0)&0xff, (self.lvalue>>8)&0xff, (self.lvalue>>16)&0xff, (self.lvalue>>24)&0xff]
        return self.build()

class updata_ioreset(cmd_base):
    head = 0x55
    id = 0x1
    len = 0
    tpye = cmd_type.CMD_WRITE_UPDATA_IORESET.value
    def __init__(self, DATA):
        super().__init__()
        self.data = DATA
    def creatpack(self):
        self.da_cmd = [self.head, self.id, self.len, self.tpye, self.data]
        return self.build()

class ad9910_reg_read(cmd_base):
    head = 0x55
    id = 0x1
    len = 0
    tpye = cmd_type.CMD_READ_AD9910_REGISTER.value
    def __init__(self, CH, ADDR):
        super().__init__()
        self.ch = CH
        self.addr = ADDR
    def creatpack(self):
        self.da_cmd = [self.head, self.id, self.len, self.tpye, self.ch, self.addr]
        return self.build()


class setchstatus(cmd_base):
    head = 0x55
    id = 0x1
    len = 0
    tpye = cmd_type.CMD_CHSTATUS.value
    def __init__(self, VALUE):
        super().__init__()
        self.value = VALUE
    def creatpack(self):
        self.da_cmd = [self.head, self.id, self.len, self.tpye, self.value]
        return self.build()

class setprofilepin(cmd_base):
    head = 0x55
    id = 0x1
    len = 0
    tpye = cmd_type.CMD_PROFILEPIN.value
    def __init__(self,CH, VALUE):
        super().__init__()
        self.ch = CH
        self.value = VALUE
    def creatpack(self):
        self.da_cmd = [self.head, self.id, self.len, self.tpye,self.ch, self.value]
        return self.build()

class setpromode(cmd_base):
    head = 0x55
    id = 0x1
    len = 0
    tpye = cmd_type.CMD_PROMODE.value
    def __init__(self, Mode):
        super().__init__()
        self.mode = Mode
    def creatpack(self):
        self.da_cmd = [self.head, self.id, self.len, self.tpye, (self.mode>>0)&0xff, (self.mode>>8)&0xff, (self.mode>>16)&0xff, (self.mode>>24)&0xff]
        return self.build()

class matrixddata(matcmd_base):
    def __init__(self, DATA, POS, LEN, JIAOYAN):
        super().__init__()
        self.data = DATA
        self.pos = POS
        self.dlen = LEN
        self.jy = JIAOYAN
    def creatpack(self):
        self.da_cmd = [self.jy&0xff, (self.dlen>>0)&0xff, (self.dlen>>8)&0xff, (self.dlen>>16)&0xff, (self.dlen>>24)&0xff]
        for i in range(0, self.dlen, 1):
            self.da_cmd.append(self.data[(i+self.pos)])
        return self.build()

class matrixddatalength(cmd_base):
    head = 0x55
    id = 0x1
    len = 0
    tpye = cmd_type.CMD_MLENGTH.value
    def __init__(self, ALLLEN):
        super().__init__()
        self.length = ALLLEN
    def creatpack(self):
        self.da_cmd = [self.head, self.id, self.len, self.tpye,
                       (self.length>>0)&0xff, (self.length>>8)&0xff, (self.length>>16)&0xff, (self.length>>24)&0xff]
        return self.build()


class devonoff(cmd_base):
    head = 0x55
    id = 0x1
    len = 0
    tpye = cmd_type.CMD_DEVONOFF.value
    def __init__(self):
        super().__init__()
    def creatpack(self):
        self.da_cmd = [self.head, self.id, self.len, self.tpye]
        return self.build()

class trigger(cmd_base):
    head = 0x55
    id = 0x1
    len = 0
    tpye = cmd_type.CMD_TRIGGER.value
    def __init__(self):
        super().__init__()
    def creatpack(self):
        self.da_cmd = [self.head, self.id, self.len, self.tpye]
        return self.build()

class profilepindefault(cmd_base):
    head = 0x55
    id = 0x1
    len = 0
    tpye = cmd_type.CMD_PINDEFULAT.value
    def __init__(self):
        super().__init__()
    def creatpack(self):
        self.da_cmd = [self.head, self.id, self.len, self.tpye]
        return self.build()

class ZWDDS1000Connect(threading.Thread):
    lock = threading.Lock()
    def __init__(self, port=''):
        super().__init__()
        try:
            self.s = serial.Serial(port, 115200, stopbits=1, bytesize=8, parity='N', timeout=5)
        except serial.SerialException:
            print("Is com port being used by other application?")
        self.DevOnOff()

    def __del__(self):
        self.s.close()

    def run(self):
        while True:
            time.sleep(3)
            self.lock.acquire()
            # 心跳包
            msg = heartpack().creatpack()
            self.s.write(msg)
            msg_byte = self._loop_read(67)  # 心跳包回复
            if msg_byte == b'0':
                print(f'心跳回复超时,设备断开连接,请检查设备......')
                status = True
                while status:
                    time.sleep(2)
                    plist = list(serial.tools.list_ports.comports())
                    print(f'设备重连中，请稍后......')
                    if len(plist) <= 0:
                        continue
                    else:
                        for i in range(len(plist)):
                            plist_0 = plist[i]
                            serialName = plist_0[0]
                            serialFd = serial.Serial(serialName, 115200, stopbits=1, bytesize=8, parity='N', timeout=5)
                            try:
                                serialFd.write(msg)
                                self.s = serialFd
                                recv_data = self._loop_read(67)  # 心跳包回复
                                if recv_data != b'0':
                                    status = False
                                    print(f'设备连接成功......')
                                    break
                                else:
                                    self.s.close()
                            except Exception:
                                pass
            self.lock.release()
    def DevOnOff(self):
        self.lock.acquire()
        s = devonoff().creatpack()
        self.s.write(s)
        rst = self._loop_read()
        a,b,c,cmd,r = struct.unpack("BBBBB", rst[0:5])
        self.DevBootFlag = r

        self.lock.release()
        if self.DevBootFlag == 0:
            print("机箱启动失败.....")
            return
        elif self.DevBootFlag == 0x1:
            print("设备已启动.....")
            return
        elif self.DevBootFlag == 0x2:
            print("AD9910启动失败...")
            return

    def _loop_read(self):
        try:
            while True:
                msg = self.s.read(524)
                if (len(msg) == 524):
                    return msg
        except  Exception as e:
            return b'0'

    def ClkSyncConfig(self, ClockSource = 0x0, SyncSource = 0x0):
        """
        来源选择
        :param ClockSource:
        :param SyncSource:
        :return:
        """
        assert 0<=ClockSource<=3
        assert 0<=SyncSource<=1

        if ClockSource == 0x0:
            HMC7044Ref = 0
            HMC7044RefIO = 0
            deviceref = 1
        elif ClockSource == 0x1:
            HMC7044Ref = 0
            HMC7044RefIO = 0
            deviceref = 0
        elif ClockSource == 0x2:
            HMC7044Ref = 1
            HMC7044RefIO = 0
            deviceref = 0
        else:
            HMC7044Ref = 0
            HMC7044RefIO = 1
            deviceref = 0

        devicesync = SyncSource

        now_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        print("{0} :发送启动命令".format(now_time))
        self.lock.acquire()
        str = Sou_sel_fun(HMC7044Ref, HMC7044RefIO,deviceref, devicesync).creatpack()
        self.s.write(str)
        while True:
            msg = self._loop_read()
            if msg != b'0':
                break;
        a, b, c, cmd, stat, excech = struct.unpack("BBBBBB", msg[0:6])
        if stat == 0x0:
            now_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            print("{0} :机箱启动失败".format(now_time))
        elif stat == 0x1:
            now_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            print("{0} :AD9910启动失败".format(now_time))
        elif stat == 0x2:
            now_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            print("{0} :机箱启动成功".format(now_time))
            self.DevBootFlag = 1
        elif stat == 0x3:
            now_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            charray = []
            for i in range(0, 8, 1):
                if excech&((0x1)<<i):
                    charray.append(',')
                    charray.append(i+1)
            rsut = ''.join('%s' % i for i in charray[1:])
            print("{0} :设备启动失败,通道{1}异常".format(now_time, rsut))

        self.lock.release()

    def SelfCheck(self):
        """
        自检
        """
        self.lock.acquire()
        str = selfcheckpack().creatpack()
        self.s.write(str)
        data = self._loop_read()
        # a, b, c, cmd, chst, hmc1, hmc2, hmc3, hmc4, hmc5, hmc6, hmc7, hmc8,  p1, p2, p3, p4, T, s= struct.unpack("17BI19s", data[0:40])
        a, b, c, cmd, bootflag,chst, hmc1, hmc2, hmc3, hmc4, hmc5, hmc6, hmc7, hmc8, p1, p2, p3, p4,pmode, pvalue1,pvalue2,pvalue3,pvalue4,pvalue5,pvalue6,pvalue7,pvalue8, t1,t2,t3,t4,s = struct.unpack('31B19s', data[0:50])
        HMCvalue = [0, 0, 0, 0, 0, 0, 0, 0]
        Pvalue = [0, 0, 0, 0, 0, 0, 0, 0]
        HMCvalue[0] = hmc1 / 2
        HMCvalue[1] = hmc2 / 2
        HMCvalue[2] = hmc3 / 2
        HMCvalue[3] = hmc4 / 2
        HMCvalue[4] = hmc5 / 2
        HMCvalue[5] = hmc6 / 2
        HMCvalue[6] = hmc7 / 2
        HMCvalue[7] = hmc8 / 2

        Pvalue[7] = pvalue1
        Pvalue[6] = pvalue2
        Pvalue[5] = pvalue3
        Pvalue[4] = pvalue4
        Pvalue[3] = pvalue5
        Pvalue[2] = pvalue6
        Pvalue[1] = pvalue7
        Pvalue[0] = pvalue8

        self.DevBootFlag = bootflag
        print("设备自检结果:")
        if self.DevBootFlag ==1:
            print("      1.设备已启动")
        else:
            print("      1.设备未启动")
        print("      2.通道开关状态:{0}".format(hex(chst)))
        for i in range(0, 8, 1):
            print("      {0}.通道{1}衰减值为:{2}dBm".format(i+3,i+1, HMCvalue[i]))
        if pmode == 0x0:
            print("      12.profilepin由外部控制")
        elif pmode == 0x1:
            print("      12.profilepin由DDR3控制")
        else:
            print("      12.profilepin由上位机控制")
        for i in range(0, 8, 1):
            print("      {0}.通道{1}:prifilepin值为:{2}".format(i+13,i+1, hex(Pvalue[i])))
        print("      22.设备ip：{0}.{1}.{2}.{3}, port: 8080".format(p1, p2, p3, p4))
        print("      23.设备id: {0}".format(s.decode("utf-8")))

        T = t1|(t2<<8)|(t3<<16)|(t4<<24)
        t = float(T)/1000
        print("      24.设备温度:{0}°C".format(t))

        self.lock.release()

    def SetRFPower(self, ch = 0x1, value = 0.0):
        """
        设置功率
        :param ch: 通道号  1-8
        :param value: 数值值
        :return:
        """
        assert 1 <= ch <= 8
        if self.DevBootFlag != 0x1:
            print("请启动设备.....")
            return

        if value<=-20:
            value = -20
        if value>=9:
            value = 9
        value = value *(-0.9799) + 9
        # print(value)

        zhengshu = value//0.5
        value = zhengshu*0.5
        # print(value)
        str = HMC542_write(ch-1, value).creatpack()
        time.sleep(0.001)
        self.s.write(str)

    def SetAttenValue(self,ch = 0x1, value = 0.0):
        """
        设置衰减值(调试使用)
        :param ch: 通道号  1-8
        :param value: 数值值
        :return:
        """
        assert 1 <= ch <= 8
        assert 0 <= value <=31.5
        if self.DevBootFlag != 0x1:
            print("请启动设备.....")
            return

        if value%0.5:
            print("请以0.5步进输入数值")
            return
        str = HMC542_write(ch-1, value).creatpack()
        time.sleep(0.001)
        self.s.write(str)

    def AD9910RegWriteSelfActing(self, ch = 0x1, addr = 0, value = '0x12345678abcdefff'):
        """
        设置AD9910寄存器的值(自己使用)
        :param ch: 通道号  1-8
        :param addr: 寄存器地址
        :param value: 寄存器的值
        :return:
        """
        assert 1 <= ch <= 8
        assert 0<=addr<=255
        if self.DevBootFlag != 0x1:
            print("请启动设备.....")
            return
        if (addr<0) | (addr>0x16) |(addr==0x5) |(addr==0x6):
            print("地址范围：0x0--0x16, 其中0x5和0x6不可访问其他均可访问,请重新输入地址.....")
            return

        self.lock.acquire()
        if value[0:2] != "0x":
            return
        length = len(value) - 2
        HightOrder = 0
        if length <= 8:
            LowOrder =  int(value[0:(length+3)], 16)
        else:
            HightOrder =  int(value[2: 10], 16)
            LowOrder = int(value[10: (length+2)], 16)

        str = ad9910_reg_write((ch-1), addr, HightOrder, LowOrder).creatpack()
        self.s.write(str)

        msg = self._loop_read()
        a, b, c, cmd, s = struct.unpack("BBBBB", msg[0:5])
        if s ==0:
            print("通道{0}：AD9910寄存器写入失败".format(ch))
        else:
            print("通道{0}：AD9910寄存器写入成功".format(ch))
        self.lock.release()
        time.sleep(0.001)

    def AD9910RegRead(self, ch = 1, addr = 0):
        assert 1 <= ch <= 8
        assert 0<=addr<=255

        if self.DevBootFlag != 0x1:
            print("请启动设备.....")
            return
        if (addr<0) | (addr>0x16) |(addr==0x5) |(addr==0x6):
            print("地址范围：0x0--0x16, 其中0x5和0x6不可访问其他均可访问,请重新输入地址.....")
            return

        self.lock.acquire()
        str = ad9910_reg_read((ch-1), addr).creatpack()
        self.s.write(str)

        msg = self._loop_read()
        a, b, c, cmd, hv, lv, promode, provalue = struct.unpack("BBBBIIBB", msg[0:14])

        slist = [32,32,32,32,32,32,16,32,32,64,64,32,64,64,64,64,64,64,64,64,32]
        if addr>4:
            addr = addr - 2;

        rdlength = slist[addr]
        if (rdlength == 16) |(rdlength == 32):
            lv = hex(lv)
            alen = len(lv)-2
            if rdlength == 16:
                rlen = 4 - alen
            else:
                rlen = 8 - alen
            lv_list = list(lv)
            for i in range(0, rlen, 1):
                lv_list.insert(2+i, '0')
            rsut = ''.join('%s' %i for i in lv_list)
            if addr>4:
                print("通道号:{0},地址:{1},AD9910寄存器内容:{2}".format(ch, addr+2, rsut))
            else:
                print("通道号:{0},地址:{1},AD9910寄存器内容:{2}".format(ch, addr, rsut))
        elif rdlength == 64:
            hv = hex(hv)
            alen = len(hv) - 2
            hlen = 8 - alen
            hv_list = list(hv)
            for i in range(0, hlen, 1):
                hv_list.insert(2 + i, '0')
            hrsut = ''.join('%s' % i for i in hv_list)

            lv = hex(lv)
            alen = len(lv) - 2
            rlen = 8 - alen
            lv_list = list(lv)
            for i in range(0, rlen, 1):
                lv_list.insert(2 + i, '0')
            lrsut = ''.join('%s' % i for i in lv_list)
            if addr>4:
                print("通道号:{0},地址:{1},AD9910寄存器内容:{2}".format(ch, addr+2, (hrsut + lrsut[2:])))
            else:
                print("通道号:{0},地址:{1},AD9910寄存器内容:{2}".format(ch, addr, (hrsut + lrsut[2:])))
        self.lock.release()
        time.sleep(0.001)

    def SetRFOnOff(self, ch = 0x0):
        """
        通道开启关闭
        :param ch: 一个字节每一位对应一个通道
        """
        assert 0<= ch <=0xff

        if self.DevBootFlag != 0x1:
            print("请启动设备.....")
            return
        str = setchstatus(ch).creatpack()
        self.s.write(str)

    def SetProfilePin(self, ch = 1, PValue = 0):
        """
        上位机控制profilepin的值, 需要先调用SetProfileMode函数设置成上位机控制模式
        :param ch: 通道号  1-8
        :param PValue:  值0-7有效
        """
        assert 0<=PValue<=7
        assert 1<=ch<=8

        if self.DevBootFlag != 0x1:
            print("请启动设备.....")
            return
        if self.ProfilepinFlag != 0x3:
            print("Profilepin模式不是上位机控制,请重新设置Profilepin模式....")
            return

        str = setprofilepin(ch-1, PValue).creatpack()
        self.s.write(str)
        time.sleep(0.001)

    def SetProfilePinMode(self, mode = 0x3):
        """
        profilepin控制模式
        :param mode: 0x0, 外部直接控制
                     0x1, 外部输入
                     0x2, DDR控制
                     0x3, 上位机控制
        """
        assert 0<=mode<=3

        if self.DevBootFlag != 0x1:
            print("请启动设备.....")
            return
        self.ProfilepinFlag = mode
        str = setpromode(mode).creatpack()
        self.s.write(str)

    def SetProfilePinSoftTrig(self):
        """
        profilepin软件触发
        """
        if self.DevBootFlag != 0x1:
            print("请启动设备.....")
            return

        str = trigger().creatpack()
        self.s.write(str)

    def SetProfilePinDRAMData(self, data = [0,1,2,3,4,5,6,7]):
        """
        矩阵数据输入函数
        """
        if self.DevBootFlag != 0x1:
            print("请启动设备.....")
            return

        if (len(data)%8) != 0:
            print("矩阵数据不是8的倍数,请重新输入矩阵数据")
            return

        self.lock.acquire()
        mvalidlen = 500     #每个包 包含的有效数据

        prtlhead = 0x18efdc01
        prtlend = 0x01dcef18
        datasize = len(data)
        for i in range(0, 4, 1):    #加包头, 有效数据长度
            data.insert(i, (prtlhead>>(i*8)&0xff))
        for i in range(0, 4, 1):
            data.insert(i+4, (datasize>> (i * 8) & 0xff))

        for i in range(0, 4, 1):        #加包尾
            data.insert(i + len(data), (prtlend >> (i * 8) & 0xff))
        for i in range(0, 4, 1):
            data.insert(i + len(data)+4, (prtlend >> (i * 8) & 0xff))

        packnum = 0
        mlen = len(data)
        zhengshu = mlen//mvalidlen
        yushu = mlen%mvalidlen

        # str = matrixddatalength(mlen).creatpack()       #先发送总数据长度
        # self.s.write(str)
        # print(zhengshu)
        # print(yushu)
        i = 0
        while i<zhengshu:
            jiaoyan = 0
            for j in range(0, mvalidlen, 1):     #校验值发送给下位机
                jiaoyan = jiaoyan ^ data[j+i*mvalidlen]

            str = matrixddata(data, i*mvalidlen, mvalidlen, jiaoyan).creatpack()  #数组 , 起始位置, 有效数据长度, 校验值
            self.s.write(str)
            msg = self._loop_read()
            a,b,c,cmd, s = struct.unpack('BBBBB',msg[0:5])
            if s == 1:
                i = i + 1
            else:
                print('第{0}包数据错误'.format(i+1))
            packnum = packnum + 1
        if yushu!=0:
            jiaoyan = 0
            for j in range(0, yushu, 1):     #校验值发送给下位机
                jiaoyan = jiaoyan ^ data[j+zhengshu*mvalidlen]
            str = matrixddata(data, zhengshu*mvalidlen, yushu, jiaoyan).creatpack()
            self.s.write(str)
            packnum = packnum + 1
        # print('包数：{0}, 总字节数：{1}'.format(packnum, packnum*1500))
        self.lock.release()

    def Generatingmatrixdata(self, dlenth = 1000000):
        """
        产生矩阵数据
        """
        mdata = []
        val = [0,0,0,0,0,0,0,0]
#         val = [0,1,2,3,4,5,6,7]
        for i in range(0, dlenth, 1):
            mdata.append(val[i%8])
            val[i%8] = val[i%8]+1;
            if val[i%8] >7:
                val[i % 8] = 0

        self.SetProfilePinDRAMData(mdata)

    def AD9910RegWrite(self, ch = 0x1, addr = 0x0, value = '0x12345678abcdefff'):
        """
        单独AD9910寄存器写入  配合UpdataIoresetSync函数使用才能生效
        :param ch: 通道号 1--8
        :param addr: 寄存器地址 0x0-0x16  其中0x5,0x6不可访问
        :param value: 数值
        """
        assert 1<=ch<=8
        if self.DevBootFlag != 0x1:
            print("请启动设备.....")
            return
        if (addr<0) | (addr>0x16) |(addr==0x5) |(addr==0x6):
            print("地址范围：0x0--0x16, 其中0x5和0x6不可访问其他均可访问,请重新输入地址.....")
            return

        if value[0:2] != "0x":
            return
        length = len(value) - 2
        HightOrder = 0
        if length <= 8:
            LowOrder =  int(value[0:(length+3)], 16)
        else:
            HightOrder =  int(value[2: 10], 16)
            LowOrder = int(value[10: (length+2)], 16)
        str = ad9910_reg_writesync(ch-1, addr, HightOrder, LowOrder).creatpack()
        self.s.write(str)
        time.sleep(0.001)

    def AD9910IoUpdate(self, ch = 0xff):
        """
        通道同步信号
        :param ch: 一个字节16进制数每一位对应一个通道
        """
        assert 0<=ch<=0xff
        if self.DevBootFlag != 0x1:
            print("请启动设备.....")
            return
        str = updata_ioreset(ch).creatpack()
        self.s.write(str)

    def SetProfilePinDefault(self):
        """
        将ch的profile pin state设置为0。
        """
        if self.DevBootFlag != 0x1:
            print("请启动设备.....")
            return

        str = profilepindefault().creatpack()
        self.s.write(str)

    def ChangeDevIp(self, ip = '192.168.1.10'):
        """
        修改ip
        """
        if self.DevBootFlag != 0x1:
            print("请启动设备.....")
            return
        str = changeip(ip).creatpack()
        if str:
            self.s.write(str)

    def FanCtrl(self, speed = 0x0):
        """
        :param speed: 风扇速度
        :return:
        """
        assert 0x0<=speed<=0x0fa0
        str = fanctrl(speed).creatpack()
        self.s.write(str)

    def SetTrigDelay(self, N = 0x0):
        """
        :param N: 范围： 0x0 ~ 0xffffffff
                硬件或软件触发后，延迟Dly*4ns的时间，才执行触发操作（ External Trig或 Internal DRAM Trig）
        :return:
        """
        assert 0x0 <= N <= 0xFFFFFFFF
        str = settirgdelay(N).creatpack()
        self.s.write(str)

    def SetToneValue(self, ch=1, num=1, amp=0.0, phase=0.0, freq=100000000):
        """
        :param ch:  1 - 8
        :param num: 1 - 8
        :param amp: 0 - 1
        :param phase: 0 - 360
        :param freq: 1Mhz - 400Mhz
        :return:
        """
        assert 1 <= ch <= 8
        assert 1 <= num <= 8
        assert 0 <= amp <= 1
        assert 0 <= phase <= 360
        assert 1000000 <= freq <= 400000000
        ASF = amp * (2**14 -1)
        POW = (phase/360)*(2**16 -1)
        FTW = (freq/1000000000)*(2**32)
        value1 = str(hex((int(ASF) << 16)+int(POW)))
        value2 = str(hex(int(FTW))).strip('0x')
        length = len(value2)
        str_list = list(value2)
        empty = ''
        if length < 8:
            for i in range(0, 8-length, 1):
                empty += '0'
            str_list.insert(0, empty)
        value2 = (''.join(str_list))
        self.AD9910RegWrite(ch, num, value1+value2)
        self.AD9910IoUpdate(0x1 << (ch-1))